"""
Flask 实用中间件集合 - 针对Todo项目
简化版本，专注于实际可用的功能
"""

from functools import wraps
from flask import request, jsonify, g, current_app
import time
import logging
from datetime import datetime
from typing import Optional, Dict, Any
from pydantic import ValidationError


class RequestLoggingMiddleware:
    """请求日志中间件 - 记录所有请求信息"""
    
    def __init__(self, app=None):
        self.app = app
        if app is not None:
            self.init_app(app)
    
    def init_app(self, app):
        """初始化中间件"""
        app.before_request(self.before_request)
        app.after_request(self.after_request)
    
    def before_request(self):
        """请求前执行"""
        g.start_time = time.time()
        g.request_id = self.generate_request_id()
        
        # 记录请求信息
        logging.info(
            f"[{g.request_id}] {request.method} {request.url} "
            f"- IP: {request.remote_addr}"
        )
    
    def after_request(self, response):
        """请求后执行"""
        if hasattr(g, 'start_time'):
            duration = time.time() - g.start_time
            logging.info(
                f"[{getattr(g, 'request_id', 'unknown')}] Response: {response.status_code} "
                f"- Duration: {duration:.3f}s"
            )
        return response
    
    @staticmethod
    def generate_request_id() -> str:
        """生成简单的请求ID"""
        import random
        import string
        return ''.join(random.choices(string.ascii_letters + string.digits, k=8))


class ValidationMiddleware:
    """数据验证中间件 - 使用Pydantic验证请求数据"""
    
    @staticmethod
    def validate_json(model_class):
        """JSON数据验证装饰器"""
        def decorator(f):
            @wraps(f)
            def decorated_function(*args, **kwargs):
                try:
                    # 获取JSON数据
                    data = request.get_json()
                    
                    if data is None:
                        return jsonify({
                            'success': False,
                            'message': '请求数据不能为空或格式错误',
                            'timestamp': datetime.now().isoformat()
                        }), 400
                    
                    # 使用Pydantic验证
                    validated_data = model_class(**data)
                    
                    # 将验证后的数据存储到g对象中
                    g.validated_data = validated_data
                    
                    return f(*args, **kwargs)
                    
                except ValidationError as e:
                    return jsonify({
                        'success': False,
                        'message': '数据验证失败',
                        'errors': ValidationMiddleware.format_validation_errors(e.errors()),
                        'timestamp': datetime.now().isoformat()
                    }), 400
                    
                except Exception as e:
                    logging.error(f"数据验证中间件错误: {str(e)}")
                    return jsonify({
                        'success': False,
                        'message': '数据处理失败',
                        'timestamp': datetime.now().isoformat()
                    }), 400
            
            return decorated_function
        return decorator
    
    @staticmethod
    def validate_query(model_class):
        """查询参数验证装饰器"""
        def decorator(f):
            @wraps(f)
            def decorated_function(*args, **kwargs):
                try:
                    # 获取查询参数
                    query_params = request.args.to_dict()
                    
                    # 使用Pydantic验证
                    validated_query = model_class(**query_params)
                    
                    # 将验证后的查询参数存储到g对象中
                    g.validated_query = validated_query
                    
                    return f(*args, **kwargs)
                    
                except ValidationError as e:
                    return jsonify({
                        'success': False,
                        'message': '查询参数验证失败',
                        'errors': ValidationMiddleware.format_validation_errors(e.errors()),
                        'timestamp': datetime.now().isoformat()
                    }), 400
                    
                except Exception as e:
                    logging.error(f"查询参数验证错误: {str(e)}")
                    return jsonify({
                        'success': False,
                        'message': '查询参数处理失败',
                        'timestamp': datetime.now().isoformat()
                    }), 400
            
            return decorated_function
        return decorator
    
    @staticmethod
    def format_validation_errors(pydantic_errors: list) -> Dict[str, Any]:
        """格式化Pydantic验证错误"""
        formatted_errors = {}
        
        for error in pydantic_errors:
            field_path = ".".join(str(x) for x in error["loc"])
            formatted_errors[field_path] = {
                "message": error["msg"],
                "type": error["type"],
                "input": error.get("input")
            }
        
        return formatted_errors


class SimpleRateLimitMiddleware:
    """简单的内存限流中间件"""
    
    def __init__(self, app=None):
        self.app = app
        self.requests: Dict[str, list] = {}  # IP -> [timestamps]
        
    def init_app(self, app):
        """初始化限流中间件"""
        app.before_request(self.cleanup_expired_records)
    
    def rate_limit(self, max_requests: int = 60, window: int = 60):
        """限流装饰器"""
        def decorator(f):
            @wraps(f)
            def decorated_function(*args, **kwargs):
                # 使用IP地址作为限流键
                key = request.remote_addr or 'unknown'
                
                # 检查限流
                if self.is_rate_limited(key, max_requests, window):
                    return jsonify({
                        'success': False,
                        'message': f'请求过于频繁，请在 {window} 秒后重试',
                        'retry_after': window,
                        'timestamp': datetime.now().isoformat()
                    }), 429
                
                return f(*args, **kwargs)
            return decorated_function
        return decorator
    
    def is_rate_limited(self, key: str, max_requests: int, window: int) -> bool:
        """检查是否触发限流"""
        now = time.time()
        window_start = now - window
        
        # 获取或创建记录
        if key not in self.requests:
            self.requests[key] = []
        
        # 移除窗口外的请求记录
        self.requests[key] = [
            req_time for req_time in self.requests[key] 
            if req_time > window_start
        ]
        
        # 检查是否超过限制
        if len(self.requests[key]) >= max_requests:
            return True
        
        # 记录当前请求
        self.requests[key].append(now)
        return False
    
    def cleanup_expired_records(self):
        """清理过期的请求记录"""
        now = time.time()
        expired_keys = []
        
        for key, request_times in self.requests.items():
            # 移除5分钟前的记录
            self.requests[key] = [
                req_time for req_time in request_times 
                if now - req_time < 300
            ]
            
            # 标记空记录的键
            if not self.requests[key]:
                expired_keys.append(key)
        
        # 删除空记录
        for key in expired_keys:
            del self.requests[key]


class ErrorHandlingMiddleware:
    """错误处理中间件"""
    
    def __init__(self, app=None):
        self.app = app
        if app is not None:
            self.init_app(app)
    
    def init_app(self, app):
        """初始化错误处理中间件"""
        app.register_error_handler(ValidationError, self.handle_validation_error)
        app.register_error_handler(404, self.handle_not_found)
        app.register_error_handler(405, self.handle_method_not_allowed)
        app.register_error_handler(500, self.handle_internal_error)
        app.register_error_handler(Exception, self.handle_generic_error)
    
    def handle_validation_error(self, e):
        """处理Pydantic验证错误"""
        return jsonify({
            'success': False,
            'message': '数据验证失败',
            'errors': ValidationMiddleware.format_validation_errors(e.errors()),
            'timestamp': datetime.now().isoformat()
        }), 400
    
    def handle_not_found(self, e):
        """处理404错误"""
        return jsonify({
            'success': False,
            'message': '请求的资源不存在',
            'path': request.path,
            'method': request.method,
            'timestamp': datetime.now().isoformat()
        }), 404
    
    def handle_method_not_allowed(self, e):
        """处理405错误"""
        allowed_methods = []
        if hasattr(e, 'valid_methods'):
            allowed_methods = list(e.valid_methods)
        
        return jsonify({
            'success': False,
            'message': f'方法 {request.method} 不被允许',
            'allowed_methods': allowed_methods,
            'timestamp': datetime.now().isoformat()
        }), 405
    
    def handle_internal_error(self, e):
        """处理500错误"""
        logging.error(f"内部服务器错误: {str(e)}")
        
        # 在开发环境显示详细错误信息
        if current_app.debug:
            return jsonify({
                'success': False,
                'message': '内部服务器错误',
                'error_detail': str(e),
                'timestamp': datetime.now().isoformat()
            }), 500
        else:
            return jsonify({
                'success': False,
                'message': '服务器内部错误，请稍后重试',
                'timestamp': datetime.now().isoformat()
            }), 500
    
    def handle_generic_error(self, e):
        """处理通用异常"""
        logging.error(f"未处理的异常: {str(e)}")
        
        return jsonify({
            'success': False,
            'message': '服务器处理请求时发生错误',
            'timestamp': datetime.now().isoformat()
        }), 500


class CORSMiddleware:
    """简单的CORS中间件"""
    
    def __init__(self, app=None, origins=None):
        self.app = app
        self.origins = origins or ['http://localhost:3000', 'http://localhost:5173']
        if app is not None:
            self.init_app(app)
    
    def init_app(self, app):
        """初始化CORS中间件"""
        app.after_request(self.after_request)
    
    def after_request(self, response):
        """添加CORS头"""
        origin = request.headers.get('Origin')
        
        if origin in self.origins:
            response.headers['Access-Control-Allow-Origin'] = origin
        elif '*' in self.origins:
            response.headers['Access-Control-Allow-Origin'] = '*'
        
        response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, PATCH, OPTIONS'
        response.headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization'
        response.headers['Access-Control-Max-Age'] = '86400'
        
        return response


def setup_middlewares(app):
    """设置所有中间件的便捷函数"""
    
    # 请求日志
    logging_middleware = RequestLoggingMiddleware(app)
    
    # 错误处理
    error_middleware = ErrorHandlingMiddleware(app)
    
    # CORS
    cors_origins = app.config.get('CORS_ORIGINS', ['http://localhost:3000'])
    cors_middleware = CORSMiddleware(app, origins=cors_origins)
    
    # 限流中间件
    rate_limit_middleware = SimpleRateLimitMiddleware(app)
    
    logging.info("所有中间件已初始化完成")
    
    return {
        'logging': logging_middleware,
        'error_handling': error_middleware,
        'cors': cors_middleware,
        'rate_limit': rate_limit_middleware,
        'validation': ValidationMiddleware
    }


# 使用示例
"""
from app.middleware import setup_middlewares, ValidationMiddleware
from app.models.task_model import CreateTaskRequest

# 在创建应用时设置中间件
middlewares = setup_middlewares(app)

# 在路由中使用验证装饰器
@tasks_bp.route('/tasks', methods=['POST'])
@ValidationMiddleware.validate_json(CreateTaskRequest)
def create_task():
    # 使用 g.validated_data 获取验证后的数据
    task_data = g.validated_data
    # ... 业务逻辑

# 使用限流装饰器
@tasks_bp.route('/tasks', methods=['GET'])
@middlewares['rate_limit'].rate_limit(max_requests=30, window=60)
def get_tasks():
    # ... 业务逻辑
"""